home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / boot / netBoot / sun3src / trap.s < prev   
Encoding:
Text File  |  1988-05-13  |  23.5 KB  |  734 lines

  1.  
  2. |
  3. |    @(#)trap.s 1.6 86/05/24    
  4. |    Copyright (c) 1986 by Sun Microsystems, Inc.
  5. |
  6. |    trap.s -- entered by hardware for all traps
  7. |
  8. |    Biggest function is handling resets.
  9. |
  10. |    If it is a power-up reset, run the diagnostics, map things a little,
  11. |    then jump to C code to deal with setting up the world and booting.
  12. |
  13. |    If it's not a power-up reset, and the Reset vectoring information
  14. |    in page zero is still good, vector to user code to deal with the
  15. |    reset.
  16. |
  17. |    The code vectored to at reset is entered with the following environment:
  18. |        Supervisor state.  Interrupt level 7.
  19. |        Enable register = ENA_NOTBOOT|ENA_PAR_GEN;
  20. |            (note that this disables interrupts and DVMA.)
  21. |            FIXME, on Sun-3 parity controls are elsewhere.
  22. |        Both contexts = 0.
  23. |        Segment map entry 0 = 0th pmeg.
  24. |        Page map entry for g_resetaddr = g_resetmap.  (Supercedes
  25. |            the above page map entries, if there's a conflict.)
  26. |        No segment map entries other than #0 are modified from their
  27. |            state before the reset.
  28. |        Page map entry #1 (0x800-0x1000) is mapped to physical memory
  29. |            page 1.
  30. |        No page map entries outside segment 0 are modified from their
  31. |            state before the reset.
  32. |        Page map entries in segment 0 cannot be depended on.
  33. |            (Note that g_resetaddr should point into segment
  34. |             zero, if you want to guarantee that you know what
  35. |             pmeg it is being mapped into.)
  36. |        SSP = pointing to stacked registers and fake exception stack.
  37. |            Base of this stack is at 0x1000.  Note that the
  38. |            pointed-to memory may not be mapped, if its map entry
  39. |            was overridden by the g_resetmap entry.  The actual
  40. |            data is in physical memory page 1.
  41. |        No other registers guaranteed.
  42. |        g_resetaddrcomp has been invalidated, and the NMI timer has
  43. |            been zapped, so a second Reset will not reinvoke the
  44. |            handler unless you fix them.  You must fix the NMI
  45. |            timer if you like NMI's.
  46. |        Memory is not guaranteed to be initialized (i.e. may have
  47. |            any data, and may contain parity errors), except
  48. |            for the stack area between SSP and 0x1000 -- and
  49. |            that might be invalid, if that chunk of physical
  50. |            memory is bad.
  51. |        Other than physical page 1, the proms have not remapped
  52. |            or otherwise messed with things.
  53. |        Code is entered at the address from g_resetaddr.
  54. |
  55. |    This code has to be written very carefully, as it it easy to make
  56. |    assumptions that aren't true.  If the code fails (eg, resets again)
  57. |    before it makes g_resetaddrcomp valid again, the PROMs will avoid
  58. |    invoking RAM code, but will just bootstrap the system from scratch
  59. |    as if they had detected a power-up reset.
  60. |
  61. |*CC***************************************************************************    
  62. |*CC*    
  63. |*CC*    4-Dec-85 RJHG    
  64. |*CC*    
  65. |*CC*        Changed dfc to sfc in 'get_enable' for correct operation.
  66. |*CC*    
  67. |*CC*        NOTE: New info on the _k2reset routine (see _k2reset in here)    
  68. |*CC*    
  69. |*CC***************************************************************************    
  70. |
  71.  
  72. #include "../sun3/assym.h"
  73. #include "../h/led.h"
  74.  
  75. #define    DUMBSTACK    0x800
  76. #define delay_2_sec    0x53aaaa
  77. #define IR_ENA_CLK5    0x20
  78.  
  79. #ifdef    SIRIUS
  80. #define ECC_CTRL_BASE   0x0FE16000
  81. #define    ECC_SYNDROME    ECC_CTRL_BASE+4
  82. #define    SYN_MASK        0x7ffffe 
  83. #define    EER_INTR        0x80    | ECC memory int pending 
  84. #define EER_UE          0x02    | r/o - UE, uncorrectable error 
  85. #define EER_CE          0x01    | r/o - CE, correctable (single bit) error 
  86. #endif    SIRIUS
  87.  
  88.  
  89.     .globl  _hardreset, _reset_common, _bootreset, _softreset, _set_evec
  90.     .globl    _exit_to_mon, _trap, _addr_error, _bus_error, _nmi
  91.     .globl  _abortent, _sendtokbd, _get_enable, _peek, _pokec
  92.     .globl    _set_enable, _set_leds, _resetinstr, _setbus, _unsetbus
  93.     .globl    _getidprom, _k2reset, _menureset
  94.  
  95. |*CC*****************************************************************************
  96. |*CC*     _k2reset:
  97. |*CC*
  98. |*CC*     This routine sets a flag to tell _hardreset that this is from the
  99. |*CC*    monitor by setting a flag value in d7.
  100. |*CC*    it does NOT do the resetting functions of a K2 command.
  101. |*CC*
  102. |*CC*****************************************************************************
  103.  
  104. _k2reset:
  105.     movl    #0x77770000, d7
  106.  
  107. | Boot PROM reset starting point.
  108. |
  109. |     This routine does the final details in preparing for a
  110. |    hard reset.  it does NOT do the functions of a K2 command
  111. |
  112. _hardreset:
  113.     movw    #CACR_CLEAR+CACR_ENABLE,a7    | Cache clear and enable bits
  114.     movc    a7,cacr
  115.  
  116.     movw    #FC_MAP,a7        | SP is already clobberred, use it
  117.     movc    a7,dfc            | Destination function code
  118.     movc    a7,sfc            | Set source function code, too.
  119.  
  120.     subl    a7,a7                   | Clear A7
  121.         movsb   a7,CONTEXTOFF           | Clear context register
  122.         movsb   a7,SMAPOFF              | Clear segment map loc 0
  123.         movsb   a7,ENABLEOFF            | Enter Boot state
  124.  
  125.     movl    d7, a7
  126. #ifdef M25
  127.     movsb   SMAPOFF+0xfe00000, d7   | Check for Watchdog reset
  128.         cmpb    #0xfe, d7
  129.         jne     _selftest               | Else, force a Power on Reset
  130.  
  131.         movsb   SMAPOFF+0xfe20000, d7   | Check for Watchdog reset
  132.         cmpb    #0xfd, d7
  133.         jne     _selftest               | Else, force a Power on Reset
  134.  
  135.         movsb   SMAPOFF+0xfef0000, d7   | Check for Watchdog reset
  136.         cmpb    #0xf7, d7
  137.         jne     _selftest               | Else, force a Power on Reset
  138. #else M25
  139.         movsb   BUSERROFF, d7
  140.         btst    #0, d7            | Watchdog Reset ?
  141.         jeq     _selftest        | If not, run Power-on diagnostics
  142. #endif M25
  143.  
  144.     movl    a7, d7
  145.     andl    #0xFFFF0000, d7         | This checks if Watchdog was in diags
  146.     cmpl    #0x77770000, d7
  147.     jeq    _selftest
  148.  
  149.         moveq   #~L_USERDOG,d7          | Entering watchdog code
  150.         movsb   d7,LEDOFF
  151.         movl    a7, d7
  152.  
  153. | FIXME, for software resets, we need to clear interrupt reg, parity, etc.
  154. | FIXME, (everything that used to be in enable reg!)
  155.  
  156.     lea    INITSP,sp        | Reset stack ptr to correct value
  157.     moveml    #0xFFFF,sp@-        | Save all regs for user's handler
  158.     movl    usp,a0            | Save USP
  159.     movl    a0,sp@(15*4)        | on top of useless SSP...
  160.  
  161.     movl    #PME_PROM,d0        | Get our own map entry
  162.     movsl    d0,PMAPOFF        | Map ourself in.
  163.     jmp    dogreset:l        | Jump to our real location
  164.  
  165. dogreset:
  166.         movl    #PME_MEM_0,d0           | Pg mapper for 0x000-7FF
  167.         movsl   d0,PMAPOFF              | Map in low memory
  168.  
  169.         moveml  sp@+,#0xFFFF            | Restore all registers.
  170.         movw    #EVEC_DOG,INITSP-6      | Fake FVO
  171.  
  172. |
  173. | The following is common to power-up, boot, soft, and watchdog resets.
  174. |
  175. _reset_common:
  176.     movw    #FC_MAP,a7        | Set map function code
  177.     movc    a7,dfc
  178.     subw    a7,a7            | Boot state, shut off rest.
  179.     movsb    a7,ENABLEOFF
  180.  
  181.     movl    #TRAPVECTOR_BASE,a7    | Set up our vector base (not at 0,
  182.     movc    a7,vbr            | which is where CPU resets put it).
  183.  
  184.     movl    #_exit_to_mon,INITSP-4    | return address if user rts'es to us
  185.     lea    INITSP-6,sp        | Reset stack ptr below stored stuff
  186.     pea     USERCODE        | fake PC = User code start addr
  187.     movw    sr,sp@-            | Save current SR (oughta be 2700)
  188.     subw    #mis_sr,sp        | SP was pointing at SR, back it
  189.                     | up so sp@(mis_sr) points there.
  190.     moveml    #0xFFFF,sp@(mis_d0)    | Store all registers, including SSP
  191.     movl    sp,d7            | Set "reset or trap" indicator.
  192.     jra    _resettrap        | Pretend we took a trap.
  193. |
  194. | SCC Menu: fake stack as if we'd taken "Diagnostic Menus reset" interrupt
  195. |
  196. _menureset:
  197.     movw    #EVEC_MENU_TSTS,d7    | Fake FVO
  198.     jra     bootsoft
  199. |
  200. | Bootstrap reset: fake stack as if we'd taken "Bootstrap reset" interrupt
  201. |
  202. _bootreset:
  203.     movw    #EVEC_BOOTING,d7    | Fake FVO
  204.     jra    bootsoft
  205. |
  206. | Soft resets (K1): fake stack as if we'd taken a "K command reset" interrupt
  207. |
  208. _softreset:
  209.     movw    #EVEC_KCMD,d7        | Fake FVO
  210. bootsoft:
  211.     jsr     _resetinstr             | Zap out Mainbus devices
  212.     clrb    INTERRUPT_BASE        | Shut off all interrupts.
  213. |
  214. | Reset the world's maps.
  215. |
  216. | This is done by a C routine that runs in boot state on a temp stack,
  217. | so we have to secure a stack area first.
  218.     movl    g_memoryworking,d6    | Save size of working RAM
  219.  
  220.     movw    #FC_MAP,d0        | SP is already clobberred, use it
  221.     movc    d0,dfc            | Destination function code
  222.     movc    d0,sfc            | Set source function code, too.
  223.  
  224.     clrl    d0            | Boot state, shut off rest.
  225.     movsb    d0,ENABLEOFF
  226.     movsb    d0,CONTEXTOFF        | Clear context register
  227.     movsb    d0,SMAPOFF        | Clear segment map loc 0
  228.     movl    #PME_MEM_0,d0        
  229.     movsl    d0,PMAPOFF        | Set page map loc 0
  230.     
  231.     lea    DUMBSTACK,a7        | Set stack pointer.
  232.  
  233.     moveq    #~L_SETUP_MAP,d0
  234.     movsb    d0,LEDOFF
  235.  
  236.     movl    d6,sp@-            | Size of working memory...
  237.     jbsr    _mapmem            | Go map/zap it.
  238.     addql    #4,sp
  239.     movl    d0,g_memoryavail    | Available memory in the system
  240.     movb    #0,g_loop        | initialize loop option
  241.  
  242.     movw    d7,INITSP-6        | Fake fvo
  243.     jra    _reset_common        | Go build rest of stack
  244. |
  245. | exit_to_mon is used if the user program returns to us via "rts" (eg, from
  246. | a "boot" command).  We just pretend she did a TRAP #1.
  247. | Note that the trap vector might not be set, so we fake it.
  248. |
  249. _exit_to_mon:
  250.     pea    _exit_to_mon        | For the next rts...
  251.     movw    #EVEC_TRAPE,sp@-    | Fake FVO
  252.     pea    _exit_to_mon        | Push fake PC that brings us back
  253.     movw    #0x2700,sp@-        | Push fake SR
  254. |
  255. |    Entry point for all traps except reset, address, and bus error.
  256. |
  257. _trap:
  258.     subw    #mis_sr,sp        | SP was pointing at SR, back it
  259.                     | up so sp@(mis_sr) points there.
  260.     moveml    #0xFFFF,sp@(mis_d0)    | Store all registers, including SSP
  261.     subl    d7,d7            | Clear "reset or trap" indicator.
  262. _resettrap:
  263.     addl    #mis_sr,sp@(mis_a7)    | Make visible SSP == trap frame
  264.     movc    usp,a0            | Drag usp out of the hardware
  265.     movl    a0,sp@(mis_usp)        | Put it in the memory image
  266.     movc    sfc,a0
  267.     movc    dfc,a1
  268.     movc    vbr,a2
  269.     movc    caar,a3
  270.     movc    cacr,a4
  271.     moveml    #0x1F00,sp@(mis_sfc)    | Store sfc, dfc, vbr, caar, cacr
  272.  
  273.     moveq    #FC_MAP,d0
  274.     movc    d0,sfc
  275.     movsb    CONTEXTOFF,d0
  276.     andb    #CONTEXTMASK,d0        | Throw away undefined bits
  277.     movl    d0,sp@(mis_context)    | Save user context reg
  278.  
  279.     orw    #0x0700,sr        | Run at interrupt level 7 now.
  280.     tstl    d7            | For resets, call monreset() first.
  281.     jeq    tomon
  282.     jbsr    _monreset        | The args are modifiable if desired.
  283. tomon:
  284.     jbsr    _monitor        | Call the interactive monitor
  285.  
  286.     movl    sp@(mis_usp),a0        | Get usp out of memory image
  287.     movc    a0,usp            | Cram it into the hardware.
  288.     moveq    #FC_MAP,d0
  289.     movc    d0,dfc
  290.     movl    sp@(mis_context),d0
  291.     movsb    d0,CONTEXTOFF
  292.     movl    sp@(mis_vbase),d0
  293.     movc    d0,vbr
  294.     movl    sp@(mis_sfc),d0
  295.     movc    d0,sfc
  296.     movl    sp@(mis_dfc),d0
  297.     movc    d0,dfc
  298.     movl    sp@(mis_caar),d0
  299.     movc    d0,caar
  300.     movl    sp@(mis_cacr),d0
  301.     movc    d0,cacr
  302.     movl    sp@(mis_a7),a0        | Grab new SSP value (prolly same)
  303.     lea    sp@(mis_sr),a1        | Get the old SSP value
  304.     cmpl    a0,a1            | Are they the same?
  305.     jeq    samestack
  306.  
  307.     clrw    a0@(6)            | Fake format/vo word
  308.     movl    sp@(mis_pc),a0@(2)    | Stack new PC&SR below new SSP
  309.     movw    sp@(mis_sr),a0@
  310.     moveml    sp@(mis_d0),#0xFFFF    | Restore all regs including new SSP
  311.     rte                | Poof, resume from error.
  312.  
  313. samestack:
  314.     moveml    sp@(mis_d0),#0x7FFF    | Restore all but SSP
  315.     addw    #mis_sr,sp        | Restore SSP to where it was after trap
  316.     rte                | Byebye...
  317. |
  318. |
  319. |    Entry point for bus and address errors.
  320. |
  321. |    Save specialized info in dedicated locations for debugging things.
  322. |    Then truncate stack to usual size, so user can resume anywhere
  323. |    instead of being able to resume in mid-cycle (sorry...).
  324. |
  325. |    They could resume in mid-cycle by simply stacking this info
  326. |    (that we save in low memory) and rts'ing.  But that's not the
  327. |    default.
  328. |
  329. _addr_error:
  330. _bus_error:
  331.     moveml    #0xFFFF,g_beregs    | Store all regs
  332.     bfextu    sp@(6){#0:#4},d0    | Get format of stack
  333. |    movb    pc@(format_size,d0),d0    | Get size of stack
  334.      lea    format_size,a0    |FIXME assembler doesn't work
  335.      movb    a0@(0,d0),d0
  336.     subql    #1,d0            | Set up for dbra.
  337.     lea    g_bestack,a0        | Get set to move all the data
  338.     movl    sp,a1
  339. BEloop:
  340.     movb    a1@+,a0@+        | Move a byte of error info
  341.     dbra    d0,BEloop        | Baby's very first loopmode loop
  342.     
  343.     movc    sfc,a0            | Save it a moment
  344.     moveq    #FC_MAP,d0        | Get the map/CPU layer function
  345.     movc    d0,sfc
  346.     movsb    BUSERROFF,d0        | Get contents of bus error reg
  347.     movb    d0,g_because        | Save for higher level code
  348.     movc    a0,sfc            | Restore previous value
  349.  
  350. | Truncate stack frame back to manageable proportions
  351.     bfextu    sp@(6){#0:#4},d0    | Get format of stack
  352. |    movb    pc@(format_size,d0),d0    | Get size of stack
  353.      lea    format_size,a0    |FIXME assembler doesn't work
  354.      movb    a0@(0,d0),d0
  355.     subql    #sizeofintstack,d0
  356.     movl    sp@,   sp@(0,d0:w)    | Move stack frame out there.
  357.     movl    sp@(4),sp@(4,d0:w)
  358.     addw    d0,sp            | Toss extended info
  359.     andw    #FVO_OFFSET,sp@(i_fvo)    | Clear "long stack frame" format
  360.     movl    g_beregs   ,d0        | Restore d0, a0, and a1
  361.     movl    g_beregs+32,a0        | (Since we clobberred them.)
  362.     movl    g_beregs+36,a1
  363.     jra    _trap            | Enter "normal" trap code
  364.  
  365. format_size:
  366.     .byte    8, 8, 12, 0, 0, 0, 0, 0    | short, throwaway, sixword
  367.     .byte    58            | 68010 berr
  368.     .byte    20, 28, 0x5C        | Coproc, short berr, long berr on 20
  369.     .byte    0, 0, 0, 0        | Unassigned
  370. |
  371. |
  372. |    Entry point for non-maskable interrupts, used to scan keyboard.
  373. |
  374. _nmi:
  375.     movl    d0,sp@-            | Save a scratch register
  376.     movb    MEMORY_ERR_BASE+MR_ER,d0 | Get parity error indicator
  377. #ifndef    SIRIUS
  378.     andb    #PER_INTR,d0        | See if it's the cause
  379. #else    SIRIUS
  380.     btst    #7,d0            | bit num for ECC int
  381. #endif    SIRIUS
  382.     jeq    not_parity        | Branch if some other interrupt
  383. |
  384. | Memory (parity or ECC) error!
  385. | if its an uncorrectible error then go on to monitor
  386. |  else print the correctible error address
  387. |  reset the ?ecc? int?
  388. |  and go on to exit
  389. #ifdef    SIRIUS
  390.     btst    #0,d0        | is ti a correctible error?
  391.     beq    10$        | its a UE so continue on to monitor
  392. | CE begins here
  393.         movl    a0,sp@-         | save addr reg
  394.         movl    d2,sp@-         |for brd cnt 
  395.         clrl    d2 
  396.         lea     ECC_SYNDROME,a0 | to get the phys addr
  397. 5$:
  398.         movl    a0@,d0          | get phys address
  399.         movl    #0,a0@          | clear out current CE report
  400.         btst    #0,d0           | is this the board?
  401.         bne     7$              | yes, run with it
  402.         addql   #1,d2           | bump brd number cnt 
  403.         addl    #0x40,a0        | bump it by nxt adrr amount
  404.         cmpl    #ECC_SYNDROME+(4*0x40),a0 |at end + 1 ?
  405.         bne     5$
  406. | this hack-- cant find right board so use last one MJC hack
  407. 7$:
  408.         andl    #SYN_MASK,d0    | mask in A<24..3>
  409.         lsll    #2,d0           | and adjust it  
  410. | now call printf
  411.         movl    d0,sp@-         | push address
  412. |have to add board number here!!! MJC
  413.         movl    d2,sp@-         | push brd num 
  414.         pea     ecc_txt         | and the text format str
  415.         jbsr    _printf
  416.         addl   #12,sp           | adjust sp back
  417.         movl    sp@+,d2         | restore d2 
  418.         movl    sp@+,a0         | restore a0 
  419. |       movl    d1,sp@-         | just set up to exit
  420.         movb    CLOCK_BASE+clk_intrreg,d0 | Is the clock chip interrupting?
  421.     bne    ce_and_clk    | yes, go handle it
  422.     movl    d1,sp@-         | just set up to exit
  423.         jra     NotSerial      | need to check for cll int MJC   NotSerial
  424. #endif    SIRIUS            | debug for now
  425. |
  426. |
  427. 10$:    movw    #EVEC_MEMERR,sp@(4+i_fvo) | Indicate that this is memory err
  428. trapout:
  429.     movl    sp@+,d0            | Restore saved register
  430.     jra    _trap            | And just trap out as usual.
  431.  
  432. not_parity:
  433.     movb    CLOCK_BASE+clk_intrreg,d0 | Is the clock chip interrupting?
  434.     beqs    trapout            | (No, report as "trap 7C".)
  435. | branch here from CE above if clk int 
  436. ce_and_clk:
  437.     andb    #~IR_ENA_CLK7,INTERRUPT_BASE    | Shut it off,
  438.     orb    #IR_ENA_CLK7,INTERRUPT_BASE    | then back on.
  439.     movb  CLOCK_BASE+clk_intrreg,d0 | Clear the interrupt
  440.     movl    d1,sp@-            | Save yet another register
  441. |
  442. | Timer interrupt: Counting the milliseconds for 1/2 second LED pulse
  443. |
  444.     movw    g_nmiclock+2,d0        | Get the clock value
  445.     addl    #1000/NMIFREQ,g_nmiclock| Count off x ms more.
  446.     movw    g_nmiclock+2,d1        | See if the "1/2 second" bit changed
  447.     eorw    d1,d0
  448.     btst    #9,d0            | (2**9 == 512, close enough)
  449.     jeq    Trykey
  450.  
  451.     movc    dfc,d1            | Save destination fn code
  452.     moveq    #FC_MAP,d0        | Set it up to access LEDs
  453.     movc    d0,dfc
  454.     movb    g_leds,d0        | Grab shadow copy of LEDs
  455.     eorb    #L_HEARTBEAT,d0        | Invert heartbeat LED
  456.     movb    d0,g_leds        | Put it back in RAM shadow loc
  457.     movsb    d0,LEDOFF        | Put it into real LEDs too
  458.     movc    d1,dfc            | Restore function code register
  459. |
  460. | Keyboard/Serial Port scanning code.
  461. |
  462. Trykey:
  463.     movl    a0,d1            | Save a0 temporarily
  464.     movl    g_keybzscc,a0        | Point to keyboard
  465.     tstb    a0@(zscc_control)    | Read to flush previous pointer.
  466.  
  467.     moveq   #0x7f, d0 
  468. 1$:     dbra    d0, 1$
  469.  
  470.     moveq    #ZSRR0_RX_READY,d0    | Bit mask for RX ready bit
  471.     andb    a0@(zscc_control),d0    | Now read it for real.
  472.     jeq    s2_notnew        | If no char around, skip.
  473.  
  474.     moveq   #0x7f, d0 
  475. 2$:     dbra    d0, 2$
  476.  
  477.     moveq    #0,d0
  478.     movb    a0@(zscc_data),d0    | Get the keycode
  479.     movl    d1,a0            | Restore A-register temp
  480.  
  481.     moveml    #0x00C0,sp@-        | Save a0, a1.  d0&d1 already saved.
  482.     movl    d0,sp@-            | Push it as argument to keypress().
  483.     jbsr    _keypress
  484.     addql    #4,sp
  485.     moveml    sp@+,#0x0300        | Restore saved registers
  486.     tstl    d0            | See if keypress() wants us to abort.
  487.     jeq    Trykey
  488.     jra    abort            | Yep, abort to monitor.
  489.  
  490. s2_notnew:
  491.     movl    d1,a0            | Restore a0 from shenanigans
  492.     tstb    g_insource        | Is input source a serial line?
  493. | FIXME, g_insource should vector.
  494.     jeq    NotSerial        | No, skip over this stuff.
  495.     movl    a0,d1            | Save away a0
  496.     movl    g_inzscc,a0        | Grab uart address
  497. | FIXME, remove next 4 lines when g_inzscc is right.
  498.     cmpb    #INUARTA,g_insource    | See if A-side or B-side
  499.     jne    Brkt1            | (B-side; a0 is OK.)
  500.     addw    #sizeofzscc,a0        | A-side is second in the chip.
  501. Brkt1:
  502.     tstb    a0@(zscc_control)    | Read to flush previous pointer.
  503.     moveq   #0x7f, d0 
  504. 1$:     dbra    d0, 1$
  505.     movb    #ZSWR0_RESET_STATUS,a0@(zscc_control)    | Avoid latch action
  506.     moveq   #0x7f, d0 
  507. 2$:     dbra    d0, 2$
  508.     movb    #ZSRR0_BREAK,d0        | Who's afraid of the big bad sign?
  509.     andb    a0@(zscc_control),d0    | Now read it for real.
  510.     movl    d1,a0            | Restore a0
  511.     cmpb    g_debounce,d0        | Is its state same as last time?
  512.     jeq    NotSerial        | Yes, don't worry about it.
  513.     movb    d0,g_debounce        | No -- remember its state,
  514.     tstb    g_init_bounce        | First time ?
  515.     jne    abort            | Not first time, Abort
  516.     movb    #1, g_init_bounce    | Remember not first time
  517. | FIXME, there will be a null in the read fifo, but we will ignore it
  518. | anyway, so probably no need to worry.  Check this.
  519.  
  520. NotSerial:
  521.     movl    sp@+,d1            | Restore other register
  522.     movl    sp@+,d0            | Restore saved register
  523.     rte                | Return from NMI
  524.  
  525. |
  526. |    Somebody wants to abort whatever is going on, and return to
  527. |    Rom Monitor control of things.  Be obliging.
  528. |
  529. abort:
  530.     movl    sp@+,d1            | Restore other register
  531.     movl    sp@+,d0            | Restore saved register
  532. _abortent:
  533.     movw    #EVEC_ABORT,sp@(i_fvo)    | Indicate that this is an abort.
  534.     jra    _trap            | And just trap out as usual.
  535.     
  536. |
  537. | Send a command byte to the keyboard if possible.
  538. | Return 1 if done, 0 if not done (Uart transmit queue full).
  539. |
  540. _sendtokbd:
  541.     movl    g_keybzscc,a0
  542.     tstb    a0@(zscc_control)    | Read to flush previous pointer.
  543.  
  544.     moveq   #0x7f, d0 
  545. 1$:     dbra    d0, 1$
  546.  
  547.     moveq   #ZSRR0_TX_READY,d0      | Bit mask for TX ready bit
  548.     andb    a0@(zscc_control),d0    | Now read it for real.
  549.     jeq    sendret            | If can't xmit, just return the 0.
  550.  
  551.     moveq    #0x7f, d0
  552. 2$:    dbra    d0, 2$
  553.  
  554.     movb    sp@(7),a0@(zscc_data)    | Write the byte to the kbd uart
  555.     moveq    #1,d0            | Indicate success
  556. sendret:rts                | Return to caller.
  557.  
  558. |
  559. | Gets the current value of the enable register.
  560. |
  561. _get_enable:
  562.     moveq    #0,d0
  563.     movc    sfc,a0            | Save SOURCE function code
  564.     moveq    #FC_MAP,d1        | Set up for map access
  565.     movc    d1,sfc
  566.     movsb    ENABLEOFF,d0        | Snarf it into d0 as result
  567.     movc    a0,sfc            | Restore SFC and exit.
  568.     rts
  569.  
  570. |
  571. | Sets the enable register to the specified value.
  572. |
  573. _set_enable:
  574.     movw    sp@(6),d0        | Grab desired value from stack
  575.     movc    dfc,a0            | Save dest function code
  576.     moveq    #FC_MAP,d1        | Set up for map access
  577.     movc    d1,dfc
  578.     movsb    d0,ENABLEOFF        | Stuff it into enable reg
  579.     movc    a0,dfc            | Restore dfc and exit.
  580.     rts
  581.  
  582. |
  583. | Set the LEDs.
  584. |
  585. _set_leds:
  586.     movc    dfc,a0            | Save dest function code
  587.     moveq    #FC_MAP,d1        | Set up for map access
  588.     movc    d1,dfc
  589.     movb    sp@(7),d0        | Get desired LED contents
  590.     movb    d0,g_leds        | Save in global RAM for readback
  591.     movsb    d0,LEDOFF        | Stuff into LED reg
  592.     movc    a0,dfc            | Restore dfc and exit.
  593.     rts
  594. |
  595. | Issue a reset instruction.
  596. |
  597. _resetinstr:
  598.     reset                | That's all.
  599. |following added to make sure int's are cleared from tod
  600. | taken from locore.s
  601. #ifdef  SIRIUS
  602.         movl    #delay_2_sec,d0
  603. del_2sec:
  604.         subql   #1,d0
  605.         bne     del_2sec
  606.  
  607.         lea     CLOCK_BASE+clk_intrreg,a4
  608.         tstb    a4@                     | read CLKADDR->clk_intrreg to clear
  609.         lea     INTERRUPT_BASE,a5
  610.         andb    #~IR_ENA_CLK5,a5@       | clear interrupt request
  611.         orb     #IR_ENA_CLK5,a5@        | and re-enable
  612.         tstb    a4@                     | clear interrupt register again,
  613. #endif  SIRIUS
  614.     rts
  615. |
  616. |    This runs the "normal" code, but sneaks back to the "buserror" code
  617. |    if a bus error occurs.  Note that on the "bus error" return, all
  618. |    register variables are trashed (restored to their values on
  619. |    entry, even though future code may have modified them).
  620. |
  621. _setbus:
  622.     movl    sp@(4),a0        | Get bus buffer area
  623.     movl    sp@,a0@            | Save return address of setbus().
  624.     moveml    a2-a7/d2-d7,a0@(12)    | Save volatile regs
  625.     movc    vbr,a1            | Find trap vectors
  626.     movl    a1@(EVEC_BUSERR),a0@(4)    | Save old bus error vector.
  627.     movl    g_busbuf,a0@(8)        | Save old busbuf address
  628.     movl    a0,g_busbuf        | Install new busbuf address
  629.     movl    #buserr,a1@(EVEC_BUSERR) | Set up bus error vector
  630.     moveq    #0,d0            | Result is zero
  631.     rts
  632.  
  633. | Entered when a bus error occurs
  634. buserr:
  635.     movl    g_busbuf,a0        | Get bus buffer pointer
  636.     moveml    a0@(12),a2-a7/d2-d7    | Restore regs
  637.     movl    a0@,sp@            | Restore return PC of setbus()
  638.     moveq    #1,d0            | Result is 1, indicating bus error
  639.     jra    unsetout        | Unset it and get out
  640. _unsetbus:
  641.     movl    sp@(4),a0        | Get bus buffer area
  642. unsetout:
  643.     movc    vbr,a1            | Find vectors
  644.     movl    a0@(4),a1@(EVEC_BUSERR)    | Restore old bus error vector
  645.     movl    a0@(8),g_busbuf        | Restore old busbuf address
  646.     rts
  647.  
  648. |
  649. | peek(addr)
  650. |
  651. | Temporarily re-routes Bus Errors, and then tries to
  652. | read a byte from the specified address.  If a Bus Error occurs,
  653. | we return -1. 
  654. |
  655. _peek:
  656.     movl    a7@(4),a0           | Get address to probe
  657.         movc    vbr,a1                  | Find trap vectors
  658.         movl    a1@(EVEC_BUSERR),d1    | Save old bus error vector.
  659.         movl    #BEhand,a1@(EVEC_BUSERR) | Set up bus error vector
  660.     movl    sp,a1            | Save stack pointer
  661.         moveq   #0,d0                   | Result is zero
  662.     movb    a0@,d0              | Read a byte.
  663. BEexit:
  664.     movl    a1,sp            | Restore stack pointer
  665.     movc    vbr,a1            | Find trap vectors
  666.         movl    d1,a1@(EVEC_BUSERR)     | Restore old bus error vector
  667.         rts
  668.  
  669. BEhand:                    | Entered when a bus error occurs
  670.         moveq   #-1,d0                  | Result is 1, indicating bus error
  671.         bra    BEexit            | Exit with flag set
  672.  
  673. |
  674. | pokec(a,c)
  675. |  
  676. | This routine is the same, but uses a store instead of a read, due to
  677. | stupid I/O devices which do not respond to reads.
  678. |
  679. | if (pokec (charpointer, bytevalue)) itfailed;
  680. |
  681. _pokec:
  682.     movl    a7@(4),a0    | Get address to probe
  683.     movc    vbr,a1          | Find trap vectors
  684.         movl    a1@(EVEC_BUSERR),d1     | Save old bus error vector.
  685.         movl    #BEhand,a1@(EVEC_BUSERR) | Set up bus error vector
  686.         movl    sp,a1            | Save stack pointer
  687.     movb    a7@(11),a0@    | Write a byte
  688.     moveq    #0,d0        | It worked; return 0 as result.
  689.     bra    BEexit
  690. |
  691. |    set_evec.s -- Set an execption vector and return the old one
  692. |
  693. |    int (*)()
  694. |    set_evec(offset, func)
  695. |        int offset;        /* Offset to vector, eg 8 for berr */
  696. |        int (*func)();        /* Function to call for it */
  697. |
  698. _set_evec:
  699.     movc    vbr,a0            | Get current vector base
  700.     addl    sp@(4),a0        | Add desired exception vector offset
  701.     movl    a0@,d0            | Return old value.
  702.     movl    sp@(8),a0@        | Set new value.
  703.     rts
  704. |
  705. | getidprom(addr, size)
  706. |
  707. | Read back <size> bytes of the ID prom and store them at <addr>.
  708. | Typical use:  getidprom(&idprom_struct, sizeof(idprom_struct));
  709. |
  710. _getidprom:
  711.     movl    sp@(4),a0    | address to move ID prom bytes to
  712.     movl    sp@(8),d1    | How many bytes to move
  713.     movl    d2,sp@-        | save a reg
  714.     movc    sfc,d0        | save source func code
  715.     movl    #FC_MAP,d2
  716.     movc    d2,sfc        | set space 3
  717.     lea    IDPROMOFF,a1    | select id prom
  718.     jra    2$        | Enter loop at bottom as usual for dbra
  719. 1$:    movsb    a1@+,d2        | get a byte
  720.     movb    d2,a0@+        | save it
  721. 2$:    dbra    d1,1$        | and loop
  722.     movc    d0,sfc        | restore sfc
  723.     movl    sp@+,d2        | restore d2
  724.     rts
  725. |**********************
  726.         .data
  727.         .even
  728. ecc_txt:
  729.         .ascii  "CE memory error at %x+%x\12\0"
  730.  
  731.  
  732.